const puppeteer = require('puppeteer');
const path = require('path');
const fs = require('fs');
const JSON5 = require('json5');
const yargs = require('yargs/yargs');
const { hideBin } = require('yargs/helpers');

// 确保输出目录存在
const outputDir = path.join(__dirname, 'output');
if (!fs.existsSync(outputDir)) {
  fs.mkdirSync(outputDir);
}

// 默认输出选项 - 只生成element和element_with_bg
const DEFAULT_OUTPUT_OPTIONS = {
  fullPage: false,    // 默认不生成全页面截图
  element: true,      // 默认生成元素截图
  elementWithBg: true,// 默认生成带背景的元素截图
  pdf: false          // 默认不生成PDF
};

/**
 * 计时辅助函数
 */
function timeMarker() {
  const startTime = Date.now();
  return {
    startTime,
    totalStartTime: startTime,
    elapsed() {
      return Date.now() - this.startTime;
    },
    totalElapsed() {
      return Date.now() - this.totalStartTime;
    },
    reset() {
      this.startTime = Date.now();
      return this;
    },
    log(label) {
      console.log(`[时间] ${label}: ${this.elapsed()}ms`);
      return this.reset();
    }
  };
}

// 浏览器实例缓存
let browserInstance = null;

/**
 * 获取浏览器实例（复用已存在的实例）
 */
async function getBrowserInstance() {
  if (!browserInstance) {
    browserInstance = await puppeteer.launch({
      headless: 'new', // 使用新的无头模式
      args: [
        '--no-sandbox', 
        '--disable-setuid-sandbox',
        '--font-render-hinting=none', // 改进字体渲染
        '--disable-dev-shm-usage', // 解决在某些Linux环境中的内存问题
        '--disable-web-security', // 禁用Web安全策略
        '--disable-extensions', // 禁用扩展，提升性能
        '--disable-audio-output', // 禁用音频输出
        '--disable-background-timer-throttling', // 减少后台计时器节流
        '--disable-backgrounding-occluded-windows', // 防止隐藏窗口被调度到后台
        '--disable-breakpad', // 禁用崩溃报告
        '--disable-component-extensions-with-background-pages' // 禁用带后台页面的组件扩展
      ],
      ignoreHTTPSErrors: true,
      protocolTimeout: 15000 // 减少超时时间为15秒
    });
    
    // 监听浏览器关闭事件，清除引用
    browserInstance.on('disconnected', () => {
      browserInstance = null;
    });
  }
  return browserInstance;
}

/**
 * 关闭浏览器实例（在进程退出前调用）
 */
async function closeBrowserInstance() {
  if (browserInstance) {
    await browserInstance.close();
    browserInstance = null;
  }
}

// 在程序退出时关闭浏览器实例
process.on('exit', () => {
  if (browserInstance) {
    browserInstance.close().catch(console.error);
  }
});

// 捕获意外错误导致的退出
process.on('SIGINT', () => {
  closeBrowserInstance().then(() => process.exit(0));
});

process.on('SIGTERM', () => {
  closeBrowserInstance().then(() => process.exit(0));
});

/**
 * 将HTML文件转换为图片
 * @param {string} htmlFile - HTML文件路径，相对于项目根目录
 * @param {string} outputPrefix - 输出文件名前缀
 * @param {boolean} transparent - 是否使用透明背景
 * @param {Object} templateData - 模板数据对象，用于动态设置HTML内容
 * @param {Object} outputOptions - 输出选项，控制生成哪些类型的文件
 */
async function convertHtmlToImage(htmlFile, outputPrefix = 'poster', transparent = true, templateData = null, outputOptions = null) {
  console.log('准备生成海报...');
  const timer = timeMarker();
  
  if (!htmlFile) {
    console.error('错误: 未提供HTML文件路径');
    return {
      success: false,
      error: '未提供HTML文件路径'
    };
  }
  
  try {
    // 处理路径中的反斜杠，确保跨平台兼容
    htmlFile = htmlFile.replace(/\\/g, '/');
    console.log(`规范化后的HTML文件路径: ${htmlFile}`);
    
    // 获取HTML文件的绝对路径
    let htmlPath;
    
    if (path.isAbsolute(htmlFile)) {
      // 如果是绝对路径，直接使用
      htmlPath = htmlFile;
    } else {
      // 否则相对于当前工作目录
      htmlPath = path.resolve(process.cwd(), htmlFile);
    }
    
    console.log(`HTML文件绝对路径: ${htmlPath}`);
    
    // 检查文件是否存在
    if (!fs.existsSync(htmlPath)) {
      console.error(`错误: 文件 ${htmlPath} 不存在`);
      return {
        success: false,
        error: `文件不存在: ${htmlPath}`
      };
    }
  
    // 提取文件名（不含扩展名）作为输出前缀
    if (!outputPrefix) {
      outputPrefix = path.basename(htmlFile, path.extname(htmlFile));
    }
  
    // 合并用户提供的选项与默认选项
    const options = { ...DEFAULT_OUTPUT_OPTIONS, ...(outputOptions || {}) };
    if (outputOptions) {
      console.log('使用自定义输出选项:', JSON.stringify(options));
    } else {
      console.log('使用默认输出选项:', JSON.stringify(DEFAULT_OUTPUT_OPTIONS));
    }
  
    // 获取或创建浏览器实例（复用）
    const browser = await getBrowserInstance();
    timer.log('获取浏览器实例');
  
    try {
      // 创建新页面
      const page = await browser.newPage();
      timer.log('创建新页面');
    
      // 设置视窗大小
      await page.setViewport({
        width: 1200, // 减小视窗大小以提高性能
        height: 800,
        deviceScaleFactor: 1.5 // 保持清晰度
      });
      timer.log('设置视窗大小');
    
      // 优化：预先确定目标选择器，减少后续查找时间
      const targetSelectors = [
        '.poster-preview-img',
        '.poster-container',
        '#custom-poster',
        '.poster-bg',
        '.dynamic-content'
      ];
      
      // 优化：预加载选择器检测脚本
      await page.evaluateOnNewDocument((selectors) => {
        window.__posterSelectors = selectors;
        window.__findPosterElement = () => {
          for (const selector of window.__posterSelectors) {
            const element = document.querySelector(selector);
            if (element) {
              const rect = element.getBoundingClientRect();
              return { 
                x: rect.x, 
                y: rect.y, 
                width: rect.width, 
                height: rect.height,
                selector: element.tagName + (element.className ? '.' + element.className.replace(/\s+/g, '.') : '')
              };
            }
          }
          const body = document.body;
          const rect = body.getBoundingClientRect();
          return { 
            x: rect.x, 
            y: rect.y, 
            width: rect.width, 
            height: rect.height,
            selector: 'BODY'
          };
        };
      }, targetSelectors);
      timer.log('预加载选择器函数');

      // 读取本地MiSans字体文件路径
      const fontsDir = path.join(__dirname, 'fonts', 'MiSans', 'woff2');
      const misansFonts = [
        { name: 'MiSans-Regular', weight: 400, style: 'normal' },
        { name: 'MiSans-Bold', weight: 700, style: 'normal' },
        { name: 'MiSans-Medium', weight: 500, style: 'normal' },
        { name: 'MiSans-Light', weight: 300, style: 'normal' },
        { name: 'MiSans-Semibold', weight: 600, style: 'normal' }
      ];
    
      // 仅检查关键字体文件是否存在
      let fontFilesExist = true;
      for (const font of misansFonts) {
        const fontFilePath = path.join(fontsDir, font.name + '.woff2');
        if (!fs.existsSync(fontFilePath)) {
          console.warn(`字体文件未找到: ${fontFilePath}`);
          fontFilesExist = false;
        }
      }
      timer.log('检查字体文件');
    
      // 优化：简化字体加载，只加载常用字重
      if (fontFilesExist) {
        // 添加字体支持
        await page.evaluateOnNewDocument(fontData => {
          const style = document.createElement('style');
          let fontFaceRules = '';
          
          fontData.forEach(font => {
            fontFaceRules += `
              @font-face {
                font-family: 'MiSans';
                font-style: ${font.style};
                font-weight: ${font.weight};
                src: url('${font.path}') format('woff2');
                font-display: swap;
              }
            `;
          });
          
          style.innerHTML = `
            ${fontFaceRules}
            body, div, p, h1, h2, h3, h4, h5, h6, span {
              font-family: 'MiSans', sans-serif !important;
            }
          `;
          
          document.head.appendChild(style);
        }, misansFonts.map(font => ({
          ...font,
          path: `file://${path.join(fontsDir, font.name + '.woff2').replace(/\\/g, '/')}`
        })));
        timer.log('注入字体样式');
      } else {
        console.log('部分字体文件不存在，将使用系统默认字体');
      }
    
      // 如果需要透明背景，设置页面背景为透明
      if (transparent) {
        await page.evaluate(() => {
          document.documentElement.style.background = 'transparent';
          document.body.style.background = 'transparent';
        });
      }
    
      // 优化：并行读取HTML文件
      const htmlContentPromise = fs.promises.readFile(htmlPath, 'utf8');
      const htmlContent = await htmlContentPromise;
      timer.log('读取HTML文件内容');
    
      // 检查是否已经有MiSans字体样式
      const hasMiSansFont = htmlContent.includes('MiSans') || htmlContent.includes('misans.css');
    
      // 创建优化版的HTML - 只有当没有MiSans字体引用且字体文件存在时才注入
      let tempHtmlPath = null;
      if (fontFilesExist && !hasMiSansFont) {
        // 简化的字体样式注入
        const fontStyle = `
          <style>
          @font-face {
            font-family: 'MiSans';
            font-style: normal;
            font-weight: 400;
            src: url('file://${path.join(fontsDir, 'MiSans-Regular.woff2').replace(/\\/g, '/')}') format('woff2');
            font-display: swap;
          }
          @font-face {
            font-family: 'MiSans';
            font-style: normal;
            font-weight: 700;
            src: url('file://${path.join(fontsDir, 'MiSans-Bold.woff2').replace(/\\/g, '/')}') format('woff2');
            font-display: swap;
          }
          body, div, p, h1, h2, h3, h4, h5, h6, span {
            font-family: 'MiSans', sans-serif !important;
          }
          </style>
        `;
        
        const modifiedContent = htmlContent.replace('</head>', `${fontStyle}</head>`);
        
        // 创建临时文件保存修改后的HTML
        const tempDir = path.join(__dirname, 'temp');
        if (!fs.existsSync(tempDir)) {
          fs.mkdirSync(tempDir);
        }
        tempHtmlPath = path.join(tempDir, `temp_${Date.now()}.html`);
        await fs.promises.writeFile(tempHtmlPath, modifiedContent);
        timer.log('创建临时HTML文件');
        
        // 使用修改后的临时HTML文件
        await page.goto(`file://${tempHtmlPath}`, { 
          waitUntil: 'domcontentloaded', // 仅等待DOM内容加载完成，减少等待时间
          timeout: 15000 // 减少超时时间
        });
        timer.log('加载临时HTML文件');
      } else {
        // 直接使用原始HTML
        await page.goto(`file://${htmlPath}`, { 
          waitUntil: 'domcontentloaded', // 仅等待DOM内容加载完成
          timeout: 15000
        });
        timer.log('加载原始HTML文件');
      }
    
      // 优化：并行执行临时文件删除操作
      if (tempHtmlPath) {
        setTimeout(() => {
          try {
            if (fs.existsSync(tempHtmlPath)) {
              fs.unlinkSync(tempHtmlPath);
            }
          } catch (err) {
            console.error('删除临时文件失败:', err);
          }
        }, 1000);
      }
    
      // 优化：等待必要的元素加载，设置更短的超时时间
      await page.waitForFunction(() => {
        return document.querySelector('.poster-container') || 
               document.querySelector('.poster-preview-img') || 
               document.querySelector('.container') ||
               document.querySelector('body');
      }, { timeout: 3000 }).catch(() => console.log('等待元素超时，继续执行'));
      timer.log('等待必要元素加载');
    
      // 优化：减少额外资源等待时间
      const waitTime = 300; // 降低从1000ms到300ms
      await page.evaluate((time) => {
        return new Promise(resolve => {
          // 减少等待时间
          setTimeout(resolve, time);
        });
      }, waitTime);
      timer.log('等待额外资源加载');
    
      // 如果提供了模板数据，注入到页面中
      if (templateData) {
        if (typeof templateData === 'string') {
          console.log('模板数据为字符串，尝试解析为JSON');
          try {
            templateData = JSON.parse(templateData);
          } catch (error) {
            console.error('解析模板数据失败:', error);
            return {
              success: false,
              error: `解析模板数据失败: ${error.message}`
            };
          }
        }
        
        // 如果有domain属性，先注入域名变量
        if (templateData.domain) {
          await page.evaluate((domain) => {
            try {
              window.domain = domain;
              return true;
            } catch (error) {
              return false;
            }
          }, templateData.domain);
        }
          
        // 注入模板数据
        await page.evaluate((data) => {
          try {
            if (typeof generateTemplate === 'function') {
              const customPoster = document.getElementById("custom-poster");
              if (customPoster) {
                const html = generateTemplate(data);
                customPoster.innerHTML = html;
                return true;
              }
            }
            return false;
          } catch (error) {
            return false;
          }
        }, templateData);
        timer.log('注入模板数据');
          
        // 优化：减少模板数据渲染等待时间
        await page.evaluate(() => new Promise(resolve => setTimeout(resolve, 200)));
      }
    
      // 在截图前再次确保背景透明（如果需要）
      if (transparent) {
        await page.evaluate(() => {
          document.documentElement.style.background = 'transparent';
          document.body.style.background = 'transparent';
        });
      }
    
      // 仅当options.fullPage为true时才生成完整页面截图
      if (options.fullPage) {
        await page.screenshot({
          path: path.join(outputDir, `${outputPrefix}_full.png`),
          fullPage: true,
          omitBackground: transparent
        });
        timer.log('生成完整页面截图');
      }
    
      // 优化：减少内容渲染等待时间
      await page.evaluate(() => new Promise(resolve => setTimeout(resolve, 100)));
    
      // 优化：使用预加载的函数快速识别海报元素
      const elementScreenshot = await page.evaluate(() => {
        // 检查预加载的函数是否存在，不存在则使用内联函数
        if (typeof window.__findPosterElement !== 'function') {
          // 按优先级尝试查找海报元素
          const selectors = [
            '.poster-preview-img',
            '.poster-container',
            '#custom-poster',
            '.poster-bg',
            '.dynamic-content'
          ];
          
          let element = null;
          for (const selector of selectors) {
            element = document.querySelector(selector);
            if (element) break;
          }
          
          // 如果没找到特定元素，使用body
          if (!element) {
            element = document.body;
          }
          
          const rect = element.getBoundingClientRect();
          return { 
            x: rect.x, 
            y: rect.y, 
            width: rect.width, 
            height: rect.height,
            selector: element.tagName + (element.className ? '.' + element.className.replace(/\s+/g, '.') : '')
          };
        }
        
        // 使用预加载的函数
        return window.__findPosterElement();
      });
      timer.log('识别主要海报元素');
    
      console.log(`找到海报元素: ${elementScreenshot.selector}`);
    
      // 仅当options.element为true时才生成元素截图
      if (options.element) {
        await page.screenshot({
          path: path.join(outputDir, `${outputPrefix}_element.png`),
          clip: {
            x: elementScreenshot.x,
            y: elementScreenshot.y,
            width: elementScreenshot.width,
            height: elementScreenshot.height
          },
          omitBackground: transparent // 启用透明背景
        });
        timer.log('生成元素截图');
        console.log(`已保存海报元素截图 (透明背景: ${transparent ? '是' : '否'})`);
      }
    
      // 仅当options.elementWithBg为true且transparent为true时才生成带背景的元素截图
      if (options.elementWithBg && transparent) {
        await page.evaluate(() => {
          document.documentElement.style.background = 'white';
          document.body.style.background = 'white';
        });
        
        await page.screenshot({
          path: path.join(outputDir, `${outputPrefix}_element_with_bg.png`),
          clip: {
            x: elementScreenshot.x,
            y: elementScreenshot.y,
            width: elementScreenshot.width,
            height: elementScreenshot.height
          },
          omitBackground: false
        });
        timer.log('生成带背景的元素截图');
        console.log('已保存带背景的海报元素截图（用于比较）');
      }
    
      // 仅当options.pdf为true时才生成PDF版本
      if (options.pdf) {
        await page.pdf({
          path: path.join(outputDir, `${outputPrefix}.pdf`),
          format: 'A4',
          printBackground: true
        });
        timer.log('生成PDF版本');
        console.log('已保存PDF版本');
      }

      // 关闭页面但保留浏览器实例
      await page.close();
      timer.log('关闭页面');

      // 返回成功信息和文件路径，只包含实际生成的文件
      console.log(`总耗时: ${timer.totalElapsed()}ms`);
      return {
        success: true,
        files: {
          fullPage: options.fullPage ? path.join(outputDir, `${outputPrefix}_full.png`) : null,
          element: options.element ? path.join(outputDir, `${outputPrefix}_element.png`) : null,
          elementWithBg: (options.elementWithBg && transparent) ? path.join(outputDir, `${outputPrefix}_element_with_bg.png`) : null,
          pdf: options.pdf ? path.join(outputDir, `${outputPrefix}.pdf`) : null
        }
      };
    
    } catch (error) {
      console.error('发生错误:', error);
      console.log(`耗时至错误: ${timer.totalElapsed()}ms`);
      return {
        success: false,
        error: error.message
      };
    }
  } catch (error) {
    console.error('发生错误:', error);
    console.log(`耗时至错误: ${timer.totalElapsed()}ms`);
    return {
      success: false,
      error: error.message
    };
  }
}

// 主函数：处理命令行参数
async function main() {
  const argv = yargs(hideBin(process.argv))
    .usage('用法: $0 <HTML文件> [选项]')
    .positional('html', {
      describe: 'HTML文件路径',
      type: 'string'
    })
    .option('output', {
      alias: 'o',
      describe: '输出文件前缀',
      type: 'string'
    })
    .option('transparent', {
      alias: 't',
      describe: '使用透明背景',
      type: 'boolean',
      default: true
    })
    .option('data', {
      alias: 'd',
      describe: '模板数据（JSON/JSON5格式字符串）',
      type: 'string',
      coerce: arg => {
        if (!arg) return null;
        try {
          // 处理命令行参数中的数据
          // 1. 移除最外层的引号（单引号或双引号）
          let jsonStr = arg.replace(/^["']|["']$/g, '');
          // 2. 处理PowerShell中的转义问题
          jsonStr = jsonStr.replace(/\\"/g, '"').replace(/\\'/g, "'");
          
          // 3. 如果是简化格式（没有引号的属性名），转换为标准JSON5格式
          if (!/^\s*{/.test(jsonStr)) {
            jsonStr = '{' + jsonStr + '}';
          }
          
          console.log('解析的数据:', jsonStr);
          return JSON5.parse(jsonStr);
        } catch (error) {
          console.error('原始数据:', arg);
          throw new Error(`模板数据解析错误: ${error.message}`);
        }
      }
    })
    .option('dataFile', {
      describe: '从文件加载模板数据(JS或JSON文件)',
      type: 'string',
      coerce: arg => {
        if (!arg) return null;
        try {
          // 如果是JS文件
          if (arg.endsWith('.js')) {
            console.log(`从JS文件加载模板数据: ${arg}`);
            return require(arg);
          }
          
          // 如果是JSON文件
          if (arg.endsWith('.json')) {
            console.log(`从JSON文件加载模板数据: ${arg}`);
            const jsonData = fs.readFileSync(arg, 'utf8');
            return JSON.parse(jsonData);
          }
          
          throw new Error(`不支持的文件类型: ${arg}. 仅支持.js或.json文件`);
        } catch (error) {
          console.error(`读取文件失败: ${arg}`);
          throw new Error(`读取数据文件错误: ${error.message}`);
        }
      }
    })
    .option('options', {
      describe: '输出选项（JSON5格式字符串）',
      type: 'string',
      coerce: arg => {
        if (!arg) return null;
        try {
          // 处理命令行参数中的数据
          let jsonStr = arg.replace(/^["']|["']$/g, '');
          jsonStr = jsonStr.replace(/\\"/g, '"').replace(/\\'/g, "'");
          
          console.log('解析的选项:', jsonStr);
          return JSON5.parse(jsonStr);
        } catch (error) {
          throw new Error(`输出选项解析错误: ${error.message}`);
        }
      }
    })
    .option('optionsFile', {
      describe: '从文件加载输出选项(JS或JSON文件)',
      type: 'string',
      coerce: arg => {
        if (!arg) return null;
        try {
          // 如果是JS文件
          if (arg.endsWith('.js')) {
            console.log(`从JS文件加载输出选项: ${arg}`);
            return require(arg);
          }
          
          // 如果是JSON文件
          if (arg.endsWith('.json')) {
            console.log(`从JSON文件加载输出选项: ${arg}`);
            const jsonData = fs.readFileSync(arg, 'utf8');
            return JSON.parse(jsonData);
          }
          
          throw new Error(`不支持的文件类型: ${arg}. 仅支持.js或.json文件`);
        } catch (error) {
          console.error(`读取文件失败: ${arg}`);
          throw new Error(`读取选项文件错误: ${error.message}`);
        }
      }
    })
    // 添加预设命令支持
    .command('elements [html]', '只生成元素截图和带背景的元素截图')
    .command('element-only [html]', '只生成元素截图')
    .command('full [html]', '生成所有类型的输出')
    .command('pdf-only [html]', '只生成PDF')
    .help()
    .alias('help', 'h')
    .example('$0 template.html -d \'{"userName":"小智","shopName":"智到店铺123"}\'', '使用JSON字符串作为模板数据')
    .example('$0 template.html --dataFile data.js', '从JS文件加载模板数据')
    .example('$0 template.html --dataFile data.json', '从JSON文件加载模板数据')
    .example('$0 --elements template.html', '使用预设命令生成元素截图')
    .example('$0 --full template.html', '生成所有类型的输出')
    .example('$0 --pdf-only template.html', '只生成PDF')
    .argv;

  let htmlFile = argv._[0] || argv.html;
  let outputPrefix = argv.output || (htmlFile ? path.basename(htmlFile, path.extname(htmlFile)) : 'output');
  let transparent = argv.transparent;
  let templateData = argv.data;
  let templateDataFile = argv.dataFile;
  let outputOptions = argv.options;
  let outputOptionsFile = argv.optionsFile;

  // 处理预设命令
  if (argv._.includes('elements')) {
    outputOptions = { fullPage: false, element: true, elementWithBg: true, pdf: false };
  } else if (argv._.includes('element-only')) {
    outputOptions = { fullPage: false, element: true, elementWithBg: false, pdf: false };
  } else if (argv._.includes('full')) {
    outputOptions = { fullPage: true, element: true, elementWithBg: true, pdf: true };
  } else if (argv._.includes('pdf-only')) {
    outputOptions = { fullPage: false, element: false, elementWithBg: false, pdf: true };
  }

  // 如果指定了模板数据文件，优先使用文件中的数据
  if (templateDataFile) {
    templateData = templateDataFile;
  }
  
  // 如果指定了选项文件，优先使用文件中的选项
  if (outputOptionsFile) {
    outputOptions = outputOptionsFile;
  }

  // 执行转换
  if (htmlFile) {
    try {
      const result = await convertHtmlToImage(htmlFile, outputPrefix, transparent, templateData, outputOptions);
      if (result.success) {
        console.log('HTML转图片完成!');
        console.log('生成的文件:');
        Object.entries(result.files).forEach(([key, path]) => {
          if (path) {
            console.log(`- ${key}: ${path}`);
          }
        });
      } else {
        console.error('转换失败:', result.error);
        process.exit(1);
      }
    } catch (err) {
      console.error('程序异常:', err);
      process.exit(1);
    }
  } else {
    yargs.showHelp();
  }

  // 清理资源并关闭浏览器实例
  await cleanup();
}

// 显示帮助信息
function showHelp() {
  console.log('HTML转图片工具 - 使用方法:');
  console.log('\n基本用法:');
  console.log('  node html2image.js <HTML文件路径> [选项]');
  console.log('\n简化命令:');
  console.log('  node html2image.js --elements <HTML文件路径> [输出文件前缀]     # 只生成元素截图和带背景的元素截图');
  console.log('  node html2image.js --element-only <HTML文件路径> [输出文件前缀] # 只生成元素截图');
  console.log('  node html2image.js --full <HTML文件路径> [输出文件前缀]         # 生成所有类型的输出');
  console.log('  node html2image.js --pdf-only <HTML文件路径> [输出文件前缀]     # 只生成PDF');
  console.log('\n示例:');
  console.log('  node html2image.js member.html                  # 使用默认设置 (只生成element和element_with_bg)');
  console.log('  node html2image.js member.html poster true      # 指定输出前缀和透明背景');
  console.log('  node html2image.js --elements member.html       # 使用简化命令生成元素截图');
  console.log('  node html2image.js --full member.html           # 生成所有类型的输出');
  console.log('\n带模板数据示例:');
  console.log('  node html2image.js member.html custom_poster true \'{"template":1,"text":"自定义文本"}\'        # 直接使用JSON字符串');
  console.log('  node html2image.js member.html --dataFile data.json                                          # 使用JSON文件');
  console.log('  node html2image.js member.html --dataFile template-data.js                                   # 使用JS模块文件');
  console.log('\n指定输出选项:');
  console.log('  node html2image.js member.html poster true --options \'{\"fullPage\":false,"element":true}\'    # 使用JSON字符串');
  console.log('  node html2image.js member.html --optionsFile options.json                                    # 使用JSON文件');
  console.log('\n默认输出选项:');
  console.log('  ' + JSON.stringify(DEFAULT_OUTPUT_OPTIONS));
}

// 清理资源并关闭浏览器实例
async function cleanup() {
  await closeBrowserInstance();
}

// 执行主函数
main();

// 导出函数
module.exports = {
  convertHtmlToImage,
  cleanup
};